<!--
* @author wn
* @date 2023/12/08 14:08:52
* @description: 购物车组件 抽离 封装
!-->
<template>
	<scroll-view
		enable-back-to-top
		refresher-enabled
		@refresherrefresh="onRefresherrefresh"
		:refresher-triggered="isTriggered"
		@scrolltolower="getMore"
		scroll-y
	>
		<!-- 已登录: 显示购物车 -->
		<template v-if="member">
			<!-- 购物车列表 -->
			<view class="cart-list" v-if="cartList.length">
				<!-- 优惠提示 -->
				<view class="tips">
					<text class="label">满减</text>
					<text class="desc">满1件, 即可享受9折优惠</text>
				</view>
				<!-- 滑动操作分区 -->
				<uni-swipe-action>
					<!-- 滑动操作项 -->
					<uni-swipe-action-item
						v-for="(item, index) in cartList"
						:key="item.skuId"
						class="cart-swipe"
					>
						<!-- 商品信息 默认插槽-->
						<view class="goods">
							<!-- 选中状态 -->
							<text
								class="checkbox"
								:class="{
									'icon-checked': item.selected,
									'icon-ring': !item.selected,
								}"
								@tap="onItemSelected(item.skuId, item.selected, index)"
							/>
							<navigator
								:url="`/pages/goods/goods?id=${item.id}`"
								hover-class="none"
								class="navigator"
							>
								<image
									mode="aspectFill"
									class="picture"
									:src="item.picture"
								></image>
								<view class="meta">
									<view class="name ellipsis">
										{{ item.name }}
									</view>
									<view class="attrsText ellipsis">{{ item.attrsText }}</view>
									<view class="price">{{ item.nowPrice }}</view>
								</view>
							</navigator>
							<!-- 商品数量 复用 SKU 插件中的 步进器组件  -->
							<view class="count">
								<!--
                <text class="text">-</text>
								<input class="input" type="number" :value="item.count" />
								<text class="text">+</text>
              -->
								<vk-data-input-number-box
									v-model="item.count"
									:min="1"
									:max="item.stock"
									:index="item.skuId"
									@change="onChangeCount($event, item.selected)"
								/>
							</view>
						</view>
						<!-- 右侧删除按钮 -->
						<template #right>
							<view class="cart-swipe-right">
								<button
									class="button delete-button"
									@tap="swipeClick(item.skuId)"
								>
									删除
								</button>
							</view>
						</template>
					</uni-swipe-action-item>
				</uni-swipe-action>
			</view>
			<!-- 购物车空状态 -->
			<view class="cart-blank" v-else>
				<image src="/static/images/blank_cart.png" class="image" />
				<text class="text">购物车还是空的，快来挑选好货吧</text>
				<navigator
					open-type="switchTab"
					url="/pages/index/index"
					hover-class="none"
				>
					<button class="button">去首页看看</button>
				</navigator>
			</view>
		</template>
		<!-- 未登录: 提示登录 -->
		<view class="login-blank" v-else>
			<text class="text">登录后可查看购物车中的商品</text>
			<navigator url="/pages/login/login" hover-class="none">
				<button class="button">去登录</button>
			</navigator>
		</view>
		<!-- 猜你喜欢 -->
		<XtxGuess ref="guessRef" />
		<!-- 底部占位空盒子 撑开底部吸顶高度 :style="{ height: toolBarHeight }" -->
		<view class="toolbar-height"></view>
	</scroll-view>
	<!-- 吸底工具栏 与购物车同步 与 scroll-view 的 refresher-enabled 冲突-->
	<view
		class="toolbar"
		v-if="member"
		:style="{
			paddingBottom: isNormal ? safeAreaInsets?.bottom + 'px' : '10rpx',
		}"
	>
		<text
			class="all"
			:class="{ 'icon-checked': allChecked, 'icon-ring': !allChecked }"
			@tap="onAllSelected(!allChecked)"
		>
			全选
		</text>
		<text class="text">合计:</text>
		<text class="amount">{{ selectedAmount }}</text>
		<button
			class="payment-button"
			:class="{ disabled: !selectedCartList.length }"
			@tap="gotoPayment"
		>
			去结算( {{ selectedCount }} )
		</button>
	</view>
</template>
<script lang="ts" setup>
import { useMemberStore } from '@/stores'
import { onShow } from '@dcloudio/uni-app'
import { storeToRefs } from 'pinia'
import { computed, ref } from 'vue'
import {
	deleteCartItemApi,
	getCartListApi,
	updateCartItemApi,
	updateCartAllSelectedApi,
} from '@/api/cart'
import { useGuess } from '@/hook/useGuess'
import type { InputNumberBoxEvent } from '@/components/vk-data-input-number-box/vk-data-input-number-box'

// 普通页面的 吸底工具栏 -- 适配底部安全距离
defineProps<{ isNormal?: Boolean }>()
// 获取安全距离
const { safeAreaInsets } = uni.getSystemInfoSync()

// 是否有 底部结算 toolbar  计算属性获取
const toolBarHeight = ref('102rpx')

// pinia 判断是否 登陆
const memberStore = useMemberStore()
const { member } = storeToRefs(memberStore)

// 购物车列表数据
const cartList = ref<CartItem[]>([])
const getCartItemList = async () => {
	const list = await getCartListApi()
	cartList.value = list
}

// 触发时机 -- tabBar 切换 以及 跳转到商品添加购物车在回来 不会触发 onload
onShow(() => {
	// 登陆后才可以调用
	if (!member) return
	getCartItemList()
})

// 购物车下拉刷新(猜你喜欢重置数据)  猜你喜欢上拉加载更多
// 猜你喜欢组合式函数调用
const { guessRef, refresh, getMore } = useGuess()

// 当前下拉刷新状态
const isTriggered = ref(false)

// 下拉刷新
const onRefresherrefresh = async () => {
	// 开始动画
	isTriggered.value = true

	// isLoading

	// 猜你喜欢重置所有数据
	refresh()
	// 购物车 下拉刷新
	await getCartItemList()

	// 关闭动画
	isTriggered.value = false
}

// 点击滑块 删除按钮
const swipeClick = (skuId: string) => {
	uni.showModal({
		title: '是否删除',
		success: async src => {
			if (src.cancel) return
			// 删除购物车
			await deleteCartItemApi({ ids: [skuId] })
			// 刷新列表
			getCartItemList()
		},
	})
}

// 修改购物车数量
const onChangeCount = async (e: InputNumberBoxEvent, selected: boolean) =>
	await updateCartItemApi(e.index, { selected, count: e.value })

/**
 * 选中状态
 * 1 每一项 是否选中 由自身的 item.selected 决定 (UI)
 * 2 计算属性 只要有一个没选中 就是 false 未选中
 * 3 全选 决定 每一项的 状态
 */
// 1 单选 -- 也可以直接传递 item:CartItem
const onItemSelected = async (
	skuId: string,
	selected: boolean,
	index: number
) => {
	// 发送请求 修改 选中状态
	await updateCartItemApi(skuId, { selected: !selected })
	// 修改本地的 item 选中状态
	cartList.value[index].selected = !selected
}

// 2 单项 决定 是否全部选中
const allChecked = computed(() => {
	/*
	// 购物车为空
	if (!cartList.value.length) return false
	// 查找 没有选中的 项
	const notSelectedItem = cartList.value.find(item => !item.selected)
	return notSelectedItem ? false : true
  */
	//  some every 返回值 为 boolean
	return !!cartList.value.length && cartList.value.every(item => item.selected)
})

// 3 全部选中按钮
const onAllSelected = async (selected: boolean) => {
	// 购物车为空
	if (!cartList.value.length) return
	// api
	await updateCartAllSelectedApi({ selected })
	// 本地
	cartList.value.forEach(item => (item.selected = selected))
}

// 计算出选中的商品列表
const selectedCartList = computed(() =>
	cartList.value.filter(item => item.selected)
)

// 结算金额 2位小数  计算属性
const selectedAmount = computed(() =>
	selectedCartList.value
		.reduce((sum, item) => sum + Number(item.nowPrice) * item.count, 0)
		.toFixed(2)
)

// 选中 总件数
const selectedCount = computed(() =>
	selectedCartList.value.reduce((sum, item) => sum + item.count, 0)
)

// 计算按钮 跳转 结算页面
const gotoPayment = () => {
	selectedCartList.value.length
		? uni.navigateTo({ url: '/pagesOrder/create/create' })
		: uni.showToast({
				title: '请先选择商品',
				icon: 'error',
		  })
}
</script>
<style lang="scss">
// 购物车列表
.cart-list {
	padding: 0 20rpx;
	// 优惠提示
	.tips {
		line-height: 1;
		margin: 30rpx 10rpx;
		font-size: 26rpx;
		color: #666;
		.label {
			display: inline-block;
			color: #fff;
			padding: 7rpx 15rpx 5rpx;
			border-radius: 6rpx;
			font-size: 24rpx;
			background-color: $primary-color;
			margin-right: 10rpx;
		}
	}
	// 购物车商品
	.goods {
		position: relative;
		display: flex;
		align-items: center;
		padding: 20rpx;
		border-radius: 10rpx;
		background-color: #fff;
		.checkbox {
			// width: 80rpx;
			// height: 100%;
			margin-right: 20rpx;
			&::before {
				font-size: 40rpx;
				color: #444;
			}

			&.icon-checked::before {
				color: $primary-color;
			}
		}
		.navigator {
			display: flex;
			.picture {
				width: 170rpx;
				height: 170rpx;
			}

			.meta {
				display: flex;
				flex: 1;
				flex-direction: column;
				justify-content: space-between;
				margin-left: 20rpx;
				.name {
					line-height: 1.6;
					font-size: 26rpx;
					color: #444;
				}

				.attrsText {
					line-height: 1.8;
					padding: 0 15rpx;
					font-size: 24rpx;
					align-self: flex-start; // 侧轴默认100%充满 改为按顺序排列
					border-radius: 4rpx;
					color: #888;
					background-color: #f7f7f8;
				}

				.price {
					line-height: 1;
					font-size: 26rpx;
					color: #444;
					margin-bottom: 2rpx;
					color: $primary-price;

					&::before {
						content: '￥';
						font-size: 80%;
					}
				}
			}
		}
		// 商品数量
		.count {
			position: absolute;
			bottom: 6rpx;
			right: 5rpx;

			display: flex;
			justify-content: space-between;
			align-items: center;
			width: 220rpx;
			height: 48rpx;

			.text {
				height: 100%;
				padding: 0 20rpx;
				font-size: 32rpx;
				color: #444;
			}

			.input {
				height: 100%;
				text-align: center;
				border-radius: 4rpx;
				font-size: 24rpx;
				color: #444;
				background-color: #f6f6f6;
			}
		}
	}

	.cart-swipe {
		display: block;
		margin: 0 0 20rpx;
	}
	.delete-button {
		display: flex;
		align-items: center;
		height: 100%;
		color: #fff;
		font-size: 26rpx;
		border-radius: 0;
		background-color: #cf4444;
	}
}

// 空状态
.cart-blank,
.login-blank {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	height: 60vh;
	.image {
		width: 400rpx;
		height: 281rpx;
	}
	.text {
		color: #444;
		font-size: 26rpx;
		margin: 30rpx 0;
	}
	.button {
		width: 240rpx !important;
		height: 60rpx;
		line-height: 60rpx;
		margin-top: 20rpx;
		font-size: 26rpx;
		border-radius: 60rpx;
		color: #fff;
		background-color: $primary-color;
	}
}
// 吸底工具栏
.toolbar {
	display: flex;
	align-items: center;
	position: fixed;
	left: 0;
	right: 0;
	bottom: var(--window-bottom);
	z-index: 1;
	// height: 102rpx;
	padding: 10rpx 20rpx;
	font-size: 14px;
	border-top: 1rpx solid #ededed;
	border-bottom: 1rpx solid #ededed;
	background-color: #fff;
	.all {
		display: flex;
		align-items: center;
		margin-left: 25rpx;
		color: #444;
		&::before {
			font-size: 40rpx;
			margin-right: 8rpx;
		}

		&.icon-checked::before {
			color: $primary-color;
		}
	}

	.text {
		margin: 0 8rpx 0 32rpx;
		color: #444;
	}

	.amount {
		flex: 1;
		font-size: 20px;
		color: #cf4444;
		transform: translateY(-2px);
		&::before {
			content: '￥';
			font-size: 60%;
		}
	}
	.payment-button {
		width: 240rpx;
		height: 72rpx;
		font-size: 13px;
		color: #fff;
		background-color: #27ba9b;
		border-radius: 72rpx;
		margin: 0 10rpx;
		&.disabled {
			opacity: 0.6;
		}
	}
}
// 底部占位空盒子
.toolbar-height {
	height: v-bind(toolBarHeight);
}
</style>
